package demo01

import "sync"

// 2. sync.Once
/*
在我们写项目的时候，程序中有很多的逻辑只需要执行一次，最典型的就是项目工程里配置文件的加载，我们只需要加载一次即可，让配置保存在内存中，下次使用的时候直接使用内存中的配置数据即可。
这里就要用到sync.Once。sync.Once可以在代码的任意位置初始化和调用，并且线程安全。sync.Once最大的作用就是延迟初始化，对于一个sync.Once变量我们并不会在程序启动的时候初始化，
而是在第一次用的它的时候才会初始化，并且只初始化这一次，初始化之后驻留在内存里，这就非常适合我们之前提到的配置文件加载场景，
设想一下，如果是在程序刚开始就加载配置，若迟迟未被使用，则既浪费了内存，又延长了程序加载时间，而sync.Once就刚好解决了这个问题。
*/

// Config 声明配置结构体Config
type Config struct{}

var instance *Config

// 声明一个sync.Once变量
var once sync.Once

// InitConfig 获取配置结构体
func InitConfig() *Config {
	/*
		只有在第一次调用InitConfig()获取Config 指针的时候才会执行once.Do(func(){instance = &Config{} })语句，
		执行完之后instance就驻留在内存中，后面再次执行InitConfig()的时候，就直接返回内存中的instance。
		2.1 与init()的区别
		有时候我们使用init()方法进行初始化，init()方法是在其所在的package首次加载时执行的，而sync.Once可以在代码的任意位置初始化和调用，是在第一次用的它的时候才会初始化。
	*/
	once.Do(func() {
		instance = &Config{}
	})
	return instance
}
